home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 23 / CU Amiga - Super CD-ROM 23 (June 1998).iso / CreatingGames / GameCreators / Inform / library / inform_library67.lha / verblibm.h < prev   
Encoding:
Text File  |  1997-09-18  |  51.7 KB  |  1,745 lines

  1. ! ----------------------------------------------------------------------------
  2. !  VERBLIBM:  Core of standard verbs library.
  3. !
  4. !  Supplied for use with Inform 6                         Serial number 970918
  5. !                                                                  Release 6/7
  6. !  (c) Graham Nelson 1993, 1994, 1995, 1996, 1997
  7. !      but freely usable (see manuals)
  8. ! ----------------------------------------------------------------------------
  9.  
  10. #IFDEF MODULE_MODE;
  11. Constant DEBUG;
  12. Constant Grammar__Version2;
  13. Include "linklpa";
  14. Include "linklv";
  15. #ENDIF;
  16.  
  17. System_file;
  18.  
  19. ! ----------------------------------------------------------------------------
  20. !  The WriteListFrom routine, a flexible object-lister taking care of
  21. !  plurals, inventory information, various formats and so on.  This is used
  22. !  by everything in the library which ever wants to list anything.
  23. !
  24. !  If there were no objects to list, it prints nothing and returns false;
  25. !  otherwise it returns true.
  26. !
  27. !  o is the object, and style is a bitmap, whose bits are given by:
  28. ! ----------------------------------------------------------------------------
  29.  
  30. Constant NEWLINE_BIT    1;    !  New-line after each entry
  31. Constant INDENT_BIT     2;    !  Indent each entry by depth
  32. Constant FULLINV_BIT    4;    !  Full inventory information after entry
  33. Constant ENGLISH_BIT    8;    !  English sentence style, with commas and and
  34. Constant RECURSE_BIT   16;    !  Recurse downwards with usual rules
  35. Constant ALWAYS_BIT    32;    !  Always recurse downwards
  36. Constant TERSE_BIT     64;    !  More terse English style
  37. Constant PARTINV_BIT  128;    !  Only brief inventory information after entry
  38. Constant DEFART_BIT   256;    !  Use the definite article in list
  39. Constant WORKFLAG_BIT 512;    !  At top level (only), only list objects
  40.                               !  which have the "workflag" attribute
  41. Constant ISARE_BIT   1024;    !  Print " is" or " are" before list
  42. Constant CONCEAL_BIT 2048;    !  Omit objects with "concealed" or "scenery":
  43.                               !  if WORKFLAG_BIT also set, then does _not_
  44.                               !  apply at top level, but does lower down
  45. Constant NOARTICLE_BIT 4096;  !  Print no articles, definite or not
  46.  
  47. [ NextEntry o odepth;
  48.   for(::)
  49.   {   o=sibling(o);
  50.       if (o==0) return 0;
  51.       if (lt_value ~=0 && o.list_together~=lt_value) continue;
  52.       if (c_style & WORKFLAG_BIT ~= 0 && odepth==0 && o hasnt workflag)
  53.           continue;
  54.       if (c_style & CONCEAL_BIT ~= 0 && (o has concealed || o has scenery))
  55.           continue;
  56.       return o;
  57.   }
  58. ];
  59.  
  60. [ WillRecurs o;
  61.   if (c_style & ALWAYS_BIT ~= 0) rtrue;
  62.   if (c_style & RECURSE_BIT == 0) rfalse;
  63.   if (o has transparent
  64.       || o has supporter
  65.       || (o has container && o has open)) rtrue;
  66.   rfalse;
  67. ];
  68.  
  69. [ ListEqual o1 o2;
  70.   if (child(o1)~=0 && WillRecurs(o1)~=0) rfalse;
  71.   if (child(o2)~=0 && WillRecurs(o2)~=0) rfalse;
  72.  
  73.   if (c_style & (FULLINV_BIT + PARTINV_BIT) ~= 0)
  74.   {   if ((o1 hasnt worn && o2 has worn)
  75.           || (o2 hasnt worn && o1 has worn)) rfalse;
  76.       if ((o1 hasnt light && o2 has light)
  77.           || (o2 hasnt light && o1 has light)) rfalse;
  78.   }
  79.  
  80.   return Identical(o1,o2);
  81. ];
  82.  
  83. [ SortTogether obj value;
  84. !  print "Sorting together possessions of ",
  85. !         (object) obj, " by value ", value, "^";
  86. !  for (x=child(obj):x~=0:x=sibling(x))
  87. !      print (the) x, " no: ", x, " lt: ", x.list_together, "^";
  88.   while (child(obj)~=0)
  89.   {   if (child(obj).list_together~=value) move child(obj) to out_obj;
  90.       else move child(obj) to in_obj;
  91.   }
  92.   while (child(in_obj)~=0)
  93.       move child(in_obj) to obj;
  94.   while (child(out_obj)~=0)
  95.       move child(out_obj) to obj;
  96. ];
  97.  
  98. [ SortOutList obj i k l;
  99. !  print "^^Sorting out list from ", (name) obj, "^  ";
  100. !  for (i=child(location):i~=0:i=sibling(i))
  101. !      print (name) i, " --> ";
  102. !  new_line;
  103.  .AP_SOL;
  104.   for (i=obj:i~=0:i=sibling(i))
  105.   {   k=i.list_together;
  106.       if (k~=0)
  107.       {   ! print "Scanning ", (name) i, " with lt=", k, "^";
  108.           for (i=sibling(i):i~=0 && i.list_together==k:) i=sibling(i);
  109.               if (i==0) rfalse;
  110.           !print "First not in block is ", (name) i,
  111.           ! " with lt=", i.list_together, "^";
  112.           for (l=sibling(i):l~=0:l=sibling(l))
  113.               if (l.list_together==k)
  114.               {   SortTogether(parent(obj), k);
  115. !  print "^^After ST:^  ";
  116. !  for (i=child(location):i~=0:i=sibling(i))
  117. !      print (name) i, " --> ";
  118. !  new_line;
  119.                   obj = child(parent(obj));
  120.                   jump AP_SOL;
  121.               }
  122.       }
  123.   }
  124. ];
  125.  
  126. [ Print__Spaces n;         ! To avoid a bug occurring in Inform 6.01 to 6.10
  127.   if (n==0) return; spaces n; ];
  128.  
  129. [ WriteListFrom o style depth;
  130.   if (o==child(parent(o)))
  131.   {   SortOutList(o); o=child(parent(o)); }
  132.   c_style=style;
  133.   wlf_indent=0; WriteListR(o,depth);
  134.   rtrue;
  135. ];
  136.  
  137. [ WriteListR o depth stack_pointer  classes_p sizes_p i j k k2 l m n q senc mr;
  138.  
  139.   if (depth>0 && o==child(parent(o)))
  140.   {   SortOutList(o); o=child(parent(o)); }
  141.   for (::)
  142.   {   if (o==0) rfalse;
  143.       if (c_style & WORKFLAG_BIT ~= 0 && depth==0 && o hasnt workflag)
  144.       {   o = sibling(o); continue; }
  145.       if (c_style & CONCEAL_BIT ~= 0
  146.           && (o has concealed || o has scenery))
  147.       {   o=sibling(o); continue; }
  148.       break;
  149.   }
  150.  
  151.   classes_p = match_classes + stack_pointer;
  152.   sizes_p   = match_list + stack_pointer;
  153.  
  154.   for (i=o,j=0:i~=0 && (j+stack_pointer)<128:i=NextEntry(i,depth),j++)
  155.   {   classes_p->j=0;
  156.       if (i.plural~=0) k++;
  157.   }
  158.  
  159.   if (c_style & ISARE_BIT ~= 0)
  160.   {   if (j==1 && o hasnt pluralname)
  161.           print (string) IS__TX; else print (string) ARE__TX;
  162.       if (c_style & NEWLINE_BIT ~= 0) print ":^"; else print (char) ' ';
  163.       c_style = c_style - ISARE_BIT;
  164.   }
  165.  
  166.   stack_pointer = stack_pointer+j+1;
  167.  
  168.   if (k<2) jump EconomyVersion;   ! It takes two to plural
  169.  
  170.   n=1;
  171.   for (i=o,k=0:k<j:i=NextEntry(i,depth),k++)
  172.       if (classes_p->k==0)
  173.       {   classes_p->k=n; sizes_p->n=1;
  174.           for (l=NextEntry(i,depth), m=k+1:l~=0 && m<j:
  175.                l=NextEntry(l,depth), m++)
  176.               if (classes_p->m==0 && i.plural~=0 && l.plural~=0)
  177.               {   if (ListEqual(i,l)==1)
  178.                   {   sizes_p->n = sizes_p->n + 1;
  179.                       classes_p->m = n;
  180.                   }
  181.               }
  182.           n++;
  183.       }
  184.   n--;
  185.  
  186.   for (i=1, j=o, k=0: i<=n: i++, senc++)
  187.   {   while (((classes_p->k) ~= i)
  188.              && ((classes_p->k) ~= -i)) { k++; j=NextEntry(j,depth); }
  189.       m=sizes_p->i;
  190.       if (j.list_together~=0 or lt_value
  191.           && ZRegion(j.list_together)==2 or 3
  192.           && j.list_together==mr) senc--;
  193.       mr=j.list_together;
  194.   }
  195.   senc--;
  196.   for (i=1, j=o, k=0, mr=0: senc>=0: i++, senc--)
  197.   {   while (((classes_p->k) ~= i)
  198.              && ((classes_p->k) ~= -i)) { k++; j=NextEntry(j,depth); }
  199.       if (j.list_together~=0 or lt_value)
  200.       {   if (j.list_together==mr) { senc++; jump Omit_FL2; }
  201.           k2=NextEntry(j,depth);
  202.           if (k2==0 || k2.list_together~=j.list_together) jump Omit_WL2;
  203.           k2=ZRegion(j.list_together);
  204.           if (k2==2 or 3)
  205.           {   q=j; listing_size=1; l=k; m=i;
  206.               while (m<n && q.list_together==j.list_together)
  207.               {   m++;
  208.                   while (((classes_p->l) ~= m)
  209.                          && ((classes_p->l) ~= -m))
  210.                   {   l++; q=NextEntry(q,depth); }
  211.                   if (q.list_together==j.list_together) listing_size++;
  212.               }
  213. !              print " [", listing_size, "] ";
  214.               if (listing_size==1) jump Omit_WL2;
  215.               if (c_style & INDENT_BIT ~= 0)
  216.                   Print__Spaces(2*(depth+wlf_indent));
  217.               if (k2==3)
  218.               {   q=0; for (l=0:l<listing_size:l++) q=q+sizes_p->(l+i);
  219.                   EnglishNumber(q); print " ";
  220.                   print (string) j.list_together;
  221.                   if (c_style & ENGLISH_BIT ~= 0) print " (";
  222.                   if (c_style & INDENT_BIT ~= 0) print ":^";
  223.               }
  224.               q=c_style;
  225.               if (k2~=3)
  226.               {   inventory_stage=1;
  227.                   parser_one=j; parser_two=depth+wlf_indent;
  228.                   if (RunRoutines(j,list_together)==1) jump Omit__Sublist2;
  229.               }
  230.               lt_value=j.list_together; listing_together=j; wlf_indent++;
  231.               WriteListR(j,depth,stack_pointer); wlf_indent--;
  232.               lt_value=0; listing_together=0;
  233.               if (k2==3)
  234.               {   if (q & ENGLISH_BIT ~= 0) print ")";
  235.               }
  236.               else
  237.               {   inventory_stage=2;
  238.                   parser_one=j; parser_two=depth+wlf_indent;
  239.                   RunRoutines(j,list_together);
  240.               }
  241.              .Omit__Sublist2;
  242.               if (q & NEWLINE_BIT ~= 0 && c_style & NEWLINE_BIT == 0)
  243.                   new_line;
  244.               c_style=q;
  245.               mr=j.list_together;
  246.               jump Omit_EL2;
  247.           }
  248.       }
  249.  
  250.      .Omit_WL2;
  251.       if (WriteBeforeEntry(j,depth,-senc)==1) jump Omit_FL2;
  252.       if (sizes_p->i == 1)
  253.       {   if (c_style & NOARTICLE_BIT ~= 0) print (name) j;
  254.           else
  255.           {   if (c_style & DEFART_BIT ~= 0) print (the) j; else print (a) j;
  256.           }
  257.       }
  258.       else
  259.       {   if (c_style & DEFART_BIT ~= 0)
  260.               PrefaceByArticle(j, 1, sizes_p->i);
  261.           print (number) sizes_p->i, " ";
  262.           PrintOrRun(j,plural,1);
  263.       }
  264.       WriteAfterEntry(j,depth,stack_pointer);
  265.  
  266.      .Omit_EL2;
  267.       if (c_style & ENGLISH_BIT ~= 0)
  268.       {   if (senc==1) print (string) AND__TX;
  269.           if (senc>1) print ", ";
  270.       }
  271.      .Omit_FL2;
  272.   }
  273.   rtrue;
  274.  
  275.   .EconomyVersion;
  276.  
  277.   n=j;
  278.  
  279.   for (i=1, j=o: i<=n: j=NextEntry(j,depth), i++, senc++)
  280.   {   if (j.list_together~=0 or lt_value
  281.           && ZRegion(j.list_together)==2 or 3
  282.           && j.list_together==mr) senc--;
  283.       mr=j.list_together;
  284.   }
  285.  
  286.   for (i=1, j=o, mr=0: i<=senc: j=NextEntry(j,depth), i++)
  287.   {   if (j.list_together~=0 or lt_value)
  288.       {   if (j.list_together==mr) { i--; jump Omit_FL; }
  289.           k=NextEntry(j,depth);
  290.           if (k==0 || k.list_together~=j.list_together) jump Omit_WL;
  291.           k=ZRegion(j.list_together);
  292.           if (k==2 or 3)
  293.           {   if (c_style & INDENT_BIT ~= 0)
  294.                   Print__Spaces(2*(depth+wlf_indent));
  295.               if (k==3)
  296.               {   q=j; l=0;
  297.                   do
  298.                   {   q=NextEntry(q,depth); l++;
  299.                   } until (q.list_together~=j.list_together);
  300.                   EnglishNumber(l); print " ";
  301.                   print (string) j.list_together;
  302.                   if (c_style & ENGLISH_BIT ~= 0) print " (";
  303.                   if (c_style & INDENT_BIT ~= 0) print ":^";
  304.               }
  305.               q=c_style;
  306.               if (k~=3)
  307.               {   inventory_stage=1;
  308.                   parser_one=j; parser_two=depth+wlf_indent;
  309.                   if (RunRoutines(j,list_together)==1) jump Omit__Sublist;
  310.               }
  311.               lt_value=j.list_together; listing_together=j; wlf_indent++;
  312.               WriteListR(j,depth,stack_pointer); wlf_indent--;
  313.               lt_value=0; listing_together=0;
  314.               if (k==3)
  315.               {   if (q & ENGLISH_BIT ~= 0) print ")";
  316.               }
  317.               else
  318.               {   inventory_stage=2;
  319.                   parser_one=j; parser_two=depth+wlf_indent;
  320.                   RunRoutines(j,list_together);
  321.               }
  322.              .Omit__Sublist;
  323.               if (q & NEWLINE_BIT ~= 0 && c_style & NEWLINE_BIT == 0) new_line;
  324.               c_style=q;
  325.               mr=j.list_together;
  326.               jump Omit_EL;
  327.           }
  328.       }
  329.      .Omit_WL;
  330.       if (WriteBeforeEntry(j,depth,i-senc)==1) jump Omit_FL;
  331.       if (c_style & NOARTICLE_BIT ~= 0) print (name) j;
  332.       else
  333.       {   if (c_style & DEFART_BIT ~= 0) print (the) j; else print (a) j;
  334.       }
  335.       WriteAfterEntry(j,depth,stack_pointer);
  336.  
  337.      .Omit_EL;
  338.       if (c_style & ENGLISH_BIT ~= 0)
  339.       {   if (i==senc-1) print (string) AND__TX;
  340.           if (i<senc-1) print ", ";
  341.       }
  342.      .Omit_FL;
  343.   }
  344. ];
  345.  
  346. [ WriteBeforeEntry o depth sentencepos  flag;
  347.   if (c_style & INDENT_BIT ~= 0) Print__Spaces(2*(depth+wlf_indent));
  348.  
  349.   if (c_style & FULLINV_BIT ~= 0)
  350.   {   if (o.invent~=0)
  351.       {   inventory_stage=1;
  352.           flag=PrintOrRun(o,invent,1);
  353.           if (flag==1)
  354.           {   if (c_style & ENGLISH_BIT ~= 0)
  355.               {   if (sentencepos == -1) print (string) AND__TX;
  356.                   if (sentencepos < -1) print ", ";
  357.               }
  358.               if (c_style & NEWLINE_BIT ~= 0) new_line;
  359.           }
  360.       }
  361.   }
  362.   return flag;
  363. ];
  364.  
  365. [ WriteAfterEntry o depth stack_p  flag flag2 flag3 p comb;
  366.  
  367.   if (c_style & PARTINV_BIT ~= 0)
  368.   {   comb=0;
  369.       if (o has light && location hasnt light) comb=comb+1;
  370.       if (o has container && o hasnt open)     comb=comb+2;
  371.       if ((o has container && (o has open || o has transparent))
  372.           && (child(o)==0)) comb=comb+4;
  373.       if (comb==1) L__M(##ListMiscellany, 1, o);
  374.       if (comb==2) L__M(##ListMiscellany, 2, o);
  375.       if (comb==3) L__M(##ListMiscellany, 3, o);
  376.       if (comb==4) L__M(##ListMiscellany, 4, o);
  377.       if (comb==5) L__M(##ListMiscellany, 5, o);
  378.       if (comb==6) L__M(##ListMiscellany, 6, o);
  379.       if (comb==7) L__M(##ListMiscellany, 7, o);
  380.   }
  381.  
  382.   if (c_style & FULLINV_BIT ~= 0)
  383.   {   if (o.invent ~= 0)
  384.       {   inventory_stage=2;
  385.           if (RunRoutines(o,invent)~=0)
  386.           {   if (c_style & NEWLINE_BIT ~= 0) new_line;
  387.               rtrue;
  388.           }
  389.       }
  390.       if (o has light && o has worn)
  391.       {    L__M(##ListMiscellany, 8); flag2=1; }
  392.       else
  393.       {   if (o has light) {  L__M(##ListMiscellany, 9, o); flag2=1; }
  394.           if (o has worn)  {  L__M(##ListMiscellany, 10, o); flag2=1; }
  395.       }
  396.       if (o has container)
  397.       {   if (o has openable)
  398.           {   if (flag2==1) print (string) AND__TX;
  399.               else L__M(##ListMiscellany, 11, o);
  400.               if (o has open)
  401.               {   if (child(o)==0) L__M(##ListMiscellany, 13, o);
  402.                   else L__M(##ListMiscellany, 12, o);
  403.               }
  404.               else
  405.               {   if (o has lockable && o has locked)
  406.                       L__M(##ListMiscellany, 15, o);
  407.                   else L__M(##ListMiscellany, 14, o);
  408.               }
  409.               flag2=1;
  410.           }
  411.           else
  412.               if (child(o)==0 && o has transparent)
  413.               {   if (flag2==1) L__M(##ListMiscellany, 16, o);
  414.                   else L__M(##ListMiscellany, 17, o);
  415.               }
  416.       }
  417.       if (flag2==1) print ")";
  418.   }
  419.  
  420.   if (c_style & CONCEAL_BIT == 0)
  421.   {   flag3 = children(o);
  422.       flag2 = child(o);
  423.   }
  424.   else
  425.   {   flag3 = 0;
  426.       objectloop (p in o)
  427.           if (p hasnt concealed && p hasnt scenery) { flag3++; flag2 = p; }
  428.   }
  429.  
  430.   if (c_style & ALWAYS_BIT ~= 0 && flag3>0)
  431.   {   if (c_style & ENGLISH_BIT ~= 0) L__M(##ListMiscellany, 18, o);
  432.       flag=1;
  433.   }
  434.  
  435.   if (c_style & RECURSE_BIT ~= 0 && flag3>0)
  436.   {   if (o has supporter)
  437.       {   if (c_style & ENGLISH_BIT ~= 0)
  438.           {   if (c_style & TERSE_BIT ~= 0)
  439.                    L__M(##ListMiscellany, 19, o);
  440.               else L__M(##ListMiscellany, 20, o);
  441.               if (o has animate) print (string) WHOM__TX;
  442.               else print (string) WHICH__TX;
  443.           }
  444.           flag=1;
  445.       }
  446.       if (o has container && (o has open || o has transparent))
  447.       {   if (c_style & ENGLISH_BIT ~= 0)
  448.           {   if (c_style & TERSE_BIT ~= 0)
  449.                    L__M(##ListMiscellany, 21, o);
  450.               else L__M(##ListMiscellany, 22, o);
  451.               if (o has animate) print (string) WHOM__TX;
  452.               else print (string) WHICH__TX;
  453.           }
  454.           flag=1;
  455.       }
  456.   }
  457.  
  458.   if (flag==1 && c_style & ENGLISH_BIT ~= 0)
  459.   {   if (flag3 > 1 || flag2 has pluralname)
  460.            print (string) ARE2__TX;
  461.       else print (string) IS2__TX;
  462.   }
  463.  
  464.   if (c_style & NEWLINE_BIT ~= 0) new_line;
  465.  
  466.   if (flag==1)
  467.   {   o = child(o);
  468.       WriteListR(o, depth+1, stack_p);
  469.       if (c_style & TERSE_BIT ~= 0) print ")";
  470.   }
  471. ];
  472.  
  473. ! ----------------------------------------------------------------------------
  474. !   A cunning routine (which could have been a daemon, but isn't, for the
  475. !   sake of efficiency) to move objects which could be in many rooms about
  476. !   so that the player never catches one not in place
  477. ! ----------------------------------------------------------------------------
  478.  
  479. [ MoveFloatingObjects i k l m address flag;
  480.   objectloop (i)
  481.   {   address=i.&found_in;
  482.       if (address~=0 && i hasnt absent)
  483.       {   if (ZRegion(address-->0)==2)
  484.           {   if (i.found_in() ~= 0) move i to location; else remove i;
  485.           }
  486.           else
  487.           {   k=i.#found_in;
  488.               for (l=0: l<k/2: l++)
  489.               {   m=address-->l;
  490.                   if (m==location || m in location)
  491.                   {   move i to location; flag = true;
  492.                   }
  493.               }
  494.               if (flag == false) remove i;
  495.           }
  496.       }
  497.   }
  498. ];
  499.  
  500. ! ----------------------------------------------------------------------------
  501. !   Two little routines for moving the player safely.
  502. ! ----------------------------------------------------------------------------
  503.  
  504. [ PlayerTo newplace flag;
  505.   move player to newplace;
  506.   while (parent(newplace)~=0) newplace=parent(newplace);
  507.   location=newplace;
  508.   real_location=location; MoveFloatingObjects();
  509.   AdjustLight(1);
  510.   if (flag==0) <Look>;
  511.   if (flag==1) { NoteArrival(); ScoreArrival(); }
  512.   if (flag==2) LookSub(1);
  513. ];
  514.  
  515. [ MovePlayer direc; <Go direc>; <Look>; ];
  516.  
  517. ! ----------------------------------------------------------------------------
  518. !   The handy YesOrNo routine, and some "meta" verbs
  519. ! ----------------------------------------------------------------------------
  520.  
  521. [ YesOrNo i;
  522.   for (::)
  523.   {
  524.    #IFV3; read buffer parse; #ENDIF;
  525.    #IFV5; read buffer parse DrawStatusLine; #ENDIF;
  526.       i=parse-->1;
  527.       if (i==YES1__WD or YES2__WD or YES3__WD) rtrue;
  528.       if (i==NO1__WD or NO2__WD or NO3__WD) rfalse;
  529.       L__M(##Quit,1); print "> ";
  530.   }
  531. ];
  532.  
  533. [ QuitSub; L__M(##Quit,2); if (YesOrNo()~=0) quit; ];
  534.  
  535. [ RestartSub; L__M(##Restart,1);
  536.   if (YesOrNo()~=0) { @restart; L__M(##Restart,2); }
  537. ];
  538.  
  539. [ RestoreSub;
  540.   restore Rmaybe;
  541.   return L__M(##Restore,1);
  542.   .RMaybe; L__M(##Restore,2);
  543. ];
  544.  
  545. [ SaveSub;
  546.   save Smaybe;
  547.   return L__M(##Save,1);
  548.   .SMaybe; L__M(##Save,2);
  549. ];
  550.  
  551. [ VerifySub;
  552.   @verify ?Vmaybe;
  553.   jump Vwrong;
  554.   .Vmaybe; return L__M(##Verify,1);
  555.   .Vwrong;
  556.   L__M(##Verify,2);
  557. ];
  558.  
  559. [ ScriptOnSub;
  560.   transcript_mode = ((0-->8) & 1);
  561.   if (transcript_mode) return L__M(##ScriptOn,1);
  562.   @output_stream 2;
  563.   if (((0-->8) & 1) == 0) return L__M(##ScriptOn,3);
  564.   L__M(##ScriptOn,2); VersionSub();
  565.   transcript_mode = true;
  566. ];
  567.     
  568. [ ScriptOffSub;
  569.   transcript_mode = ((0-->8) & 1);
  570.   if (transcript_mode == false) return L__M(##ScriptOff,1);
  571.   L__M(##ScriptOff,2);
  572.   @output_stream -2;
  573.   if ((0-->8) & 1) return L__M(##ScriptOff,3);
  574.   transcript_mode = false;
  575. ];
  576.  
  577. [ NotifyOnSub; notify_mode=1; L__M(##NotifyOn); ];
  578. [ NotifyOffSub; notify_mode=0; L__M(##NotifyOff); ];
  579.  
  580. [ Places1Sub i j k;
  581.   L__M(##Places);
  582.   objectloop(i has visited) j++;
  583.  
  584.   objectloop(i has visited)
  585.   {   print (name) i; k++;
  586.       if (k==j) ".";
  587.       if (k==j-1) print (string) AND__TX; else print ", ";
  588.   }
  589. ];
  590. [ Objects1Sub i j f;
  591.   L__M(##Objects,1);
  592.   objectloop(i has moved)
  593.   {   f=1; print (the) i; j=parent(i);
  594.       if (j==player)
  595.       {   if (i has worn) L__M(##Objects, 3);
  596.           else L__M(##Objects, 4);
  597.           jump obj__ptd;
  598.       }
  599.  
  600.       if (j has animate)   { L__M(##Objects, 5); jump obj__ptd; }
  601.       if (j has visited)   { L__M(##Objects, 6, j); jump obj__ptd; }
  602.       if (j has container) { L__M(##Objects, 8, j); jump obj__ptd; }
  603.       if (j has supporter) { L__M(##Objects, 9, j); jump obj__ptd; }
  604.       if (j has enterable) { L__M(##Objects, 7, j); jump obj__ptd; }
  605.  
  606.       L__M(##Objects, 10);
  607.       .obj__ptd; new_line;
  608.   }
  609.   if (f==0) L__M(##Objects,2);
  610. ];
  611.  
  612. ! ----------------------------------------------------------------------------
  613. !   The scoring system
  614. ! ----------------------------------------------------------------------------
  615.  
  616. [ ScoreSub;
  617.   L__M(##Score);
  618.   PrintRank();
  619. ];
  620.  
  621. [ Achieved num;
  622.   if (task_done->num==0)
  623.   {   task_done->num=1;
  624.       score = score + task_scores->num;
  625.   }
  626. ];
  627.  
  628. [ PANum m n;
  629.   print "  ";
  630.   n=m;
  631.   if (n<0)    { n=-m; n=n*10; }
  632.   if (n<10)   { print "   "; jump panuml; }
  633.   if (n<100)  { print "  "; jump panuml; }
  634.   if (n<1000) { print " "; }
  635. .panuml;
  636.   print m, " ";
  637. ];
  638.  
  639. [ FullScoreSub i;
  640.   ScoreSub();
  641.   if (score==0 || TASKS_PROVIDED==1) rfalse;
  642.   new_line;
  643.   L__M(##FullScore,1);
  644.  
  645.   for (i=0:i<NUMBER_TASKS:i++)
  646.       if (task_done->i==1)
  647.       {   PANum(task_scores->i);
  648.           PrintTaskName(i);
  649.       }
  650.   
  651.   if (things_score~=0)
  652.   {   PANum(things_score); L__M(##FullScore,2); }
  653.   if (places_score~=0)
  654.   {   PANum(places_score); L__M(##FullScore,3); }
  655.   new_line; PANum(score); L__M(##FullScore,4);
  656. ];
  657.  
  658. ! ----------------------------------------------------------------------------
  659. !   Real verbs start here: Inventory
  660. ! ----------------------------------------------------------------------------
  661.  
  662. [ InvWideSub;
  663.   inventory_style = FULLINV_BIT + ENGLISH_BIT + RECURSE_BIT;
  664.   <Inv>;
  665. ];
  666.  
  667. [ InvTallSub;
  668.   inventory_style = FULLINV_BIT + INDENT_BIT + NEWLINE_BIT + RECURSE_BIT;
  669.   <Inv>;
  670. ];
  671.  
  672. [ InvSub x;
  673.   if (child(player)==0) return L__M(##Inv,1);
  674.   if (inventory_style==0) return InvTallSub();
  675.  
  676.   L__M(##Inv,2);
  677.   if (inventory_style & NEWLINE_BIT ~= 0) print ":^"; else print " ";
  678.  
  679.   WriteListFrom(child(player), inventory_style, 1);
  680.   if (inventory_style & ENGLISH_BIT ~= 0) print ".^";
  681.  
  682. #IFNDEF MANUAL_PRONOUNS;
  683.   objectloop(x in player) PronounNotice(x);
  684. #ENDIF;
  685.  
  686.   AfterRoutines();
  687. ];
  688.  
  689. ! ----------------------------------------------------------------------------
  690. !   The object tree and determining the possibility of moves
  691. ! ----------------------------------------------------------------------------
  692.  
  693. [ CommonAncestor o1 o2 i j;
  694.   !  Find the nearest object indirectly containing o1 and o2,
  695.   !  or return 0 if there is no common ancestor.
  696.  
  697.   i = o1;
  698.   while (i ~= 0)
  699.   {
  700.       j = o2;
  701.       while (j ~= 0)
  702.       {   if (j == i) return i;
  703.           j = parent(j);
  704.       }
  705.       i = parent(i);
  706.   }
  707.   return 0;
  708. ];
  709.  
  710. [ IndirectlyContains o1 o2;
  711.   !  Does o1 indirectly contain o2?  (Same as testing if their common
  712.   !  ancestor is o1.)
  713.  
  714.   while (o2~=0)
  715.   {   if (o1==o2) rtrue;
  716.       o2=parent(o2);
  717.   }
  718.   rfalse;
  719. ];
  720.  
  721. [ ObjectScopedBySomething item i j k l m;
  722.   i = item;
  723.   while (parent(i) ~= 0) i=parent(i);
  724.   objectloop (j .& add_to_scope)
  725.   {   l = j.&add_to_scope;
  726.       k = (j.#add_to_scope)/2;
  727.       if (l-->0 ofclass Routine) continue;
  728.       for (m=0:m<k:m++)
  729.           if (l-->m == i)
  730.               return j;
  731.   }
  732.   rfalse;
  733. ];
  734.  
  735. [ ObjectIsUntouchable item flag1 flag2 ancestor i;
  736.  
  737.   ! Determine if there's any barrier preventing the player from moving
  738.   ! things to "item".  Return false if no barrier; otherwise print a
  739.   ! suitable message and return true.
  740.   ! If flag1 is set, do not print any message.
  741.   ! If flag2 is set, also apply Take/Remove restrictions.
  742.  
  743.   ! If the item has been added to scope by something, it's first necessary
  744.   ! for that something to be touchable.
  745.  
  746.   i = ObjectScopedBySomething(item);
  747.   if (i ~= 0)
  748.   {   if (ObjectIsUntouchable(i)) return;
  749.       ! An item immediately added to scope
  750.   }
  751.  
  752.   ancestor = CommonAncestor(player, item);
  753.  
  754.   ! First, a barrier between the player and the ancestor.  The player
  755.   ! can only be in a sequence of enterable objects, and only closed
  756.   ! containers form a barrier.
  757.  
  758.   if (player ~= ancestor)
  759.   {   i = parent(player);
  760.       while (i~=ancestor)
  761.       {   if (i has container && i hasnt open)
  762.           {   if (flag1) rtrue;
  763.               return L__M(##Take,9,i);
  764.           }
  765.           i = parent(i);
  766.       }
  767.   }
  768.  
  769.   ! Second, a barrier between the item and the ancestor.  The item can
  770.   ! be carried by someone, part of a piece of machinery, in or on top
  771.   ! of something and so on.
  772.  
  773.   if (item ~= ancestor)
  774.   {   i = parent(item);
  775.       while (i~=ancestor)
  776.       {   if (flag2 && i hasnt container && i hasnt supporter)
  777.           {   if (i has animate)
  778.               {   if (flag1) rtrue;
  779.                   return L__M(##Take,6,i);
  780.               }
  781.               if (i has transparent)
  782.               {   if (flag1) rtrue;
  783.                   return L__M(##Take,7,i);
  784.               }
  785.               if (flag1) rtrue;
  786.               return L__M(##Take,8,item);
  787.           }
  788.           if (i has container && i hasnt open)
  789.           {   if (flag1) rtrue;
  790.               return L__M(##Take,9,i);
  791.           }
  792.           i = parent(i);
  793.       }
  794.   }
  795.   rfalse;
  796. ];
  797.  
  798. [ AttemptToTakeObject item     ancestor after_recipient i j k;
  799.   ! Try to transfer the given item to the player: return false
  800.   ! if successful, true if unsuccessful, printing a suitable message
  801.   ! in the latter case.
  802.  
  803.   ! People cannot ordinarily be taken.
  804.   if (item == player) return L__M(##Take,2);
  805.   if (item has animate) return L__M(##Take,3,item);
  806.  
  807.   ancestor = CommonAncestor(player, item);
  808.  
  809.   if (ancestor == 0)
  810.   {   i = ObjectScopedBySomething(item);
  811.       if (i ~= 0) ancestor = CommonAncestor(player, i);
  812.   }
  813.  
  814.   ! Are player and item in totally different places?
  815.  
  816.   if (ancestor == 0) return L__M(##Take,8,item);
  817.  
  818.   ! Is the player indirectly inside the item?
  819.   if (ancestor == item) return L__M(##Take,4,item);
  820.  
  821.   ! Does the player already directly contain the item?
  822.   if (item in player) return L__M(##Take,5,item);
  823.  
  824.   ! Can the player touch the item, or is there (e.g.) a closed container
  825.   ! in the way?
  826.   if (ObjectIsUntouchable(item,false,true)) return;
  827.  
  828.   ! The item is now known to be accessible.
  829.  
  830.   ! Consult the immediate possessor of the item, if it's in a container
  831.   ! which the player is not in.
  832.  
  833.   i=parent(item);
  834.   if (i ~= ancestor && (i has container || i has supporter))
  835.   {   after_recipient=i;
  836.       k=action; action=##LetGo;
  837.       if (RunRoutines(i,before)~=0) { action=k; rtrue; }
  838.       action=k;
  839.   }
  840.  
  841.   if (item has scenery) return L__M(##Take,10,item);
  842.   if (item has static)  return L__M(##Take,11,item);
  843.  
  844.   ! The item is now known to be available for taking.  Is the player
  845.   ! carrying too much?  If so, possibly juggle items into the rucksack
  846.   ! to make room.
  847.  
  848.   k=0; objectloop (j in player) if (j hasnt worn) k++;
  849.  
  850.   if (k >= ValueOrRun(player,capacity))
  851.   {   if (SACK_OBJECT~=0)
  852.       {   if (parent(SACK_OBJECT)~=player)
  853.               return L__M(##Take,12);
  854.           j=0;
  855.           objectloop (k in player) 
  856.               if (k~=SACK_OBJECT && k hasnt worn && k hasnt light) j=k;
  857.  
  858.           if (j~=0)
  859.           {   L__M(##Take,13,j);
  860.               keep_silent = 1; <Insert j SACK_OBJECT>; keep_silent = 0;
  861.               if (j notin SACK_OBJECT) rtrue;
  862.           }
  863.           else return L__M(##Take,12);
  864.       }
  865.       else return L__M(##Take,12);
  866.   }
  867.  
  868.   ! Transfer the item.
  869.  
  870.   move item to player;
  871.  
  872.   ! Send "after" message to the object letting go of the item, if any.
  873.  
  874.   if (after_recipient~=0)
  875.   {   k=action; action=##LetGo;
  876.       if (RunRoutines(after_recipient,after)~=0) { action=k; rtrue; }
  877.       action=k;
  878.   }
  879.   rfalse;
  880. ];
  881.  
  882. ! ----------------------------------------------------------------------------
  883. !   Object movement verbs
  884. ! ----------------------------------------------------------------------------
  885.  
  886. [ TakeSub;
  887.   if (onotheld_mode==0 || noun notin player)
  888.       if (AttemptToTakeObject(noun)) rtrue;
  889.   if (AfterRoutines()==1) rtrue;
  890.   notheld_mode=onotheld_mode;
  891.   if (notheld_mode==1 || keep_silent==1) rtrue;
  892.   L__M(##Take,1);
  893. ];
  894.  
  895. [ RemoveSub i;
  896.   i=parent(noun);
  897.   if (i has container && i hasnt open) return L__M(##Remove,1,noun);
  898.   if (i~=second) return L__M(##Remove,2,noun);
  899.   if (i has animate) return L__M(##Take,6,i);
  900.   if (AttemptToTakeObject(noun)) rtrue;
  901.   action=##Take;   if (AfterRoutines()==1) rtrue;
  902.   action=##Remove; if (AfterRoutines()==1) rtrue;
  903.  
  904.   if (keep_silent==1) rtrue;
  905.   return L__M(##Remove,3,noun);
  906. ];
  907.  
  908. [ DropSub;
  909.   if (noun == player) return L__M(##PutOn, 4);
  910.   if (noun in parent(player)) return L__M(##Drop,1,noun);
  911.   if (noun notin player) return L__M(##Drop,2,noun);
  912.   if (noun has worn)
  913.   {   L__M(##Drop,3,noun);
  914.       <Disrobe noun>;
  915.       if (noun has worn) rtrue;
  916.   }
  917.   move noun to parent(player);
  918.   if (AfterRoutines()==1) rtrue;
  919.   if (keep_silent==1) rtrue;
  920.   return L__M(##Drop,4,noun);
  921. ];
  922.  
  923. [ PutOnSub ancestor;
  924.   receive_action=##PutOn; 
  925.   if (second == d_obj || player in second) <<Drop noun>>;
  926.   if (parent(noun)~=player) return L__M(##PutOn,1,noun);
  927.  
  928.   ancestor = CommonAncestor(noun, second);
  929.   if (ancestor == noun) return L__M(##PutOn,2,noun);
  930.   if (ObjectIsUntouchable(second)) return;
  931.  
  932.   if (second ~= ancestor)
  933.   {   action=##Receive;
  934.       if (RunRoutines(second,before)~=0) { action=##PutOn; return; }
  935.       action=##PutOn;
  936.   }
  937.   if (second hasnt supporter) return L__M(##PutOn,3,second);
  938.   if (ancestor == player) return L__M(##PutOn,4);
  939.   if (noun has worn)
  940.   {   L__M(##PutOn,5,noun); <Disrobe noun>; if (noun has worn) return;
  941.   }
  942.  
  943.   if (children(second)>=ValueOrRun(second,capacity))
  944.       return L__M(##PutOn,6,second);
  945.  
  946.   move noun to second;
  947.  
  948.   if (AfterRoutines()==1) return;
  949.  
  950.   if (second ~= ancestor)
  951.   {   action=##Receive;
  952.       if (RunRoutines(second,after)~=0) { action=##PutOn; return; }
  953.       action=##PutOn;
  954.   }
  955.   if (keep_silent==1) return;
  956.   if (multiflag==1) return L__M(##PutOn,7);
  957.   L__M(##PutOn,8,noun);
  958. ];
  959.  
  960. [ InsertSub ancestor;
  961.   receive_action = ##Insert;
  962.   if (second==d_obj || player in second) <<Drop noun>>;
  963.   if (parent(noun)~=player) return L__M(##Insert,1,noun);
  964.  
  965.   ancestor = CommonAncestor(noun, second);
  966.   if (ancestor == noun) return L__M(##Insert, 5, noun);
  967.   if (ObjectIsUntouchable(second)) return;
  968.  
  969.   if (second ~= ancestor)
  970.   {   action=##Receive;
  971.       if (RunRoutines(second,before)~=0) { action=##Insert; rtrue; }
  972.       action=##Insert;
  973.       if (second has container && second hasnt open)
  974.           return L__M(##Insert,3,second);
  975.   }
  976.   if (second hasnt container) return L__M(##Insert,2,second);
  977.  
  978.   if (noun has worn)
  979.   {   L__M(##Insert,6,noun); <Disrobe noun>; if (noun has worn) return;
  980.   }
  981.  
  982.   if (children(second) >= ValueOrRun(second,capacity))
  983.       return L__M(##Insert,7,second);
  984.  
  985.   move noun to second;
  986.  
  987.   if (AfterRoutines()==1) rtrue;
  988.  
  989.   if (second ~= ancestor)
  990.   {   action=##Receive;
  991.       if (RunRoutines(second,after)~=0) { action=##Insert; rtrue; }
  992.       action=##Insert;
  993.   }
  994.   if (keep_silent==1) rtrue;
  995.   if (multiflag==1) return L__M(##Insert,8,noun);
  996.   L__M(##Insert,9,noun);
  997. ];
  998.  
  999. ! ----------------------------------------------------------------------------
  1000. !   Empties and transfers are routed through the actions above
  1001. ! ----------------------------------------------------------------------------
  1002.  
  1003. [ TransferSub;
  1004.   if (noun notin player && AttemptToTakeObject(noun)) return;
  1005.   if (second has container) <<Insert noun second>>;
  1006.   if (second has supporter) <<PutOn noun second>>;
  1007.   <<Drop noun>>;
  1008. ];
  1009.  
  1010. [ EmptySub;
  1011.   second=d_obj; EmptyTSub();
  1012. ];
  1013.  
  1014. [ EmptyTSub i j;
  1015.   if (ObjectIsUntouchable(noun)) return;
  1016.   if (noun hasnt container) return L__M(##EmptyT,1,noun);
  1017.   if (noun hasnt open) return L__M(##EmptyT,2,noun);
  1018.   if (second~=d_obj)
  1019.   {   if (second hasnt container) return L__M(##EmptyT,1,second);
  1020.       if (second hasnt open) return L__M(##EmptyT,2,second);
  1021.   }
  1022.   i=child(noun);
  1023.   if (i==0) return L__M(##EmptyT,3,noun);
  1024.   while (i~=0)
  1025.   {   j=sibling(i); print (name) i, ": ";
  1026.       <Transfer i second>;
  1027.       i=j;
  1028.   }
  1029. ];
  1030.  
  1031. ! ----------------------------------------------------------------------------
  1032. !   Gifts
  1033. ! ----------------------------------------------------------------------------
  1034.  
  1035. [ GiveSub;
  1036.   if (parent(noun)~=player) return L__M(##Give,1,noun);
  1037.   if (second==player)  return L__M(##Give,2,noun);
  1038.   if (RunLife(second,##Give)~=0) rfalse;
  1039.   L__M(##Give,3,second);
  1040. ];
  1041.  
  1042. [ GiveRSub; <Give second noun>; ];
  1043.  
  1044. [ ShowSub;
  1045.   if (parent(noun)~=player) return L__M(##Show,1,noun);
  1046.   if (second==player) <<Examine noun>>;
  1047.   if (RunLife(second,##Show)~=0) rfalse;
  1048.   L__M(##Show,2,second);
  1049. ];
  1050.  
  1051. [ ShowRSub; <Show second noun>; ];
  1052.  
  1053. ! ----------------------------------------------------------------------------
  1054. !   Travelling around verbs
  1055. ! ----------------------------------------------------------------------------
  1056.  
  1057. [ EnterSub ancestor j k;
  1058.   if (noun has door || noun in compass) <<Go noun>>;
  1059.  
  1060.   if (player in noun) return L__M(##Enter,1,noun);
  1061.   if (noun hasnt enterable) return L__M(##Enter,2,noun);
  1062.   if (noun has container && noun hasnt open) return L__M(##Enter,3,noun);
  1063.  
  1064.   if (parent(player) ~= parent(noun))
  1065.   {   ancestor = CommonAncestor(player, noun);
  1066.       if (ancestor == player or 0) return L__M(##Enter,4,noun);
  1067.       while (player notin ancestor)
  1068.       {   j = parent(player);
  1069.           if (parent(j) ~= ancestor || noun ~= ancestor)
  1070.           {   L__M(##Enter,6,j);
  1071.               k = keep_silent; keep_silent = 1;
  1072.           }    
  1073.           <Exit>;
  1074.           keep_silent = k;
  1075.           if (player in j) return;
  1076.       }
  1077.       if (player in noun) return;
  1078.       if (noun notin ancestor)
  1079.       {   j = parent(noun);
  1080.           while (parent(j) ~= ancestor) j = parent(j);
  1081.           L__M(##Enter,7,j);
  1082.           k = keep_silent; keep_silent = 1;
  1083.           <Enter j>;
  1084.           keep_silent = k;
  1085.           if (player notin j) return;
  1086.           <<Enter noun>>;
  1087.       }
  1088.   }
  1089.  
  1090.   move player to noun;
  1091.   if (AfterRoutines()==1) rtrue;
  1092.   if (keep_silent==1) rtrue;
  1093.   L__M(##Enter,5,noun);
  1094.   Locale(noun);
  1095. ];
  1096.  
  1097. [ GetOffSub;
  1098.   if (parent(player)==noun) <<Exit>>;
  1099.   L__M(##GetOff,1,noun);
  1100. ];
  1101.  
  1102. [ ExitSub p;
  1103.   p=parent(player);
  1104.   if (p==location || (location==thedark && p==real_location))
  1105.   {   if ((location.out_to~=0)
  1106.           || (location==thedark && real_location.out_to~=0)) <<Go out_obj>>;
  1107.       return L__M(##Exit,1);
  1108.   }
  1109.   if (p has container && p hasnt open)
  1110.       return L__M(##Exit,2,p);
  1111.  
  1112.   move player to parent(p);
  1113.  
  1114.   if (AfterRoutines()==1) rtrue;
  1115.   if (keep_silent==1) rtrue;
  1116.   L__M(##Exit,3,p); LookSub(1);
  1117. ];
  1118.  
  1119. [ VagueGoSub; L__M(##VagueGo); ];
  1120.  
  1121. [ GoInSub;
  1122.   <<Go in_obj>>;
  1123. ];
  1124.  
  1125. [ GoSub i j k df movewith thedir old_loc;
  1126.  
  1127.   old_loc = location;
  1128.   movewith=0;
  1129.   i=parent(player);
  1130.   if ((location~=thedark && i~=location)
  1131.       || (location==thedark && i~=real_location))
  1132.   {   j=location;
  1133.       if (location==thedark) location=real_location;
  1134.       k=RunRoutines(i,before); if (k~=3) location=j;
  1135.       if (k==1)
  1136.       {   movewith=i; i=parent(i); jump gotroom; }
  1137.       if (k==0) L__M(##Go,1,i); rtrue;
  1138.   }
  1139.   .gotroom;
  1140.   thedir=noun.door_dir;
  1141.   if (ZRegion(thedir)==2) thedir=RunRoutines(noun,door_dir);
  1142.   
  1143.   j=i.thedir; k=ZRegion(j);
  1144.   if (k==3) { print (string) j; new_line; rfalse; }
  1145.   if (k==2) { j=RunRoutines(i,thedir);
  1146.               if (j==1) rtrue;
  1147.             }
  1148.  
  1149.   if (k==0 || j==0)
  1150.   {   if (i.cant_go ~= 0) PrintOrRun(i, cant_go);
  1151.       rfalse;
  1152.   }
  1153.  
  1154.   if (j has door)
  1155.   {   if (j has concealed) return L__M(##Go,2);
  1156.       if (j hasnt open)
  1157.       {   if (noun==u_obj) return L__M(##Go,3,j);
  1158.           if (noun==d_obj) return L__M(##Go,4,j);
  1159.           return L__M(##Go,5,j);
  1160.       }
  1161.       k=RunRoutines(j,door_to);
  1162.       if (k==0) return L__M(##Go,6,j);
  1163.       if (k==1) rtrue;
  1164.       j = k;
  1165.   }
  1166.   if (movewith==0) move player to j; else move movewith to j;
  1167.  
  1168.   location=j; MoveFloatingObjects();
  1169.   df=OffersLight(j);
  1170.   if (df~=0) { location=j; lightflag=1; }
  1171.   else
  1172.   {   if (old_loc == thedark)
  1173.       {   DarkToDark();
  1174.           if (deadflag~=0) rtrue;
  1175.       }
  1176.       real_location=j;
  1177.       location=thedark; lightflag=0;
  1178.   }
  1179.   if (AfterRoutines()==1) rtrue;
  1180.   if (keep_silent==1) rtrue;
  1181.   LookSub(1);
  1182. ];
  1183.  
  1184. ! ----------------------------------------------------------------------------
  1185. !   Describing the world.  SayWhatsOn(object) does just that (producing
  1186. !   no text if nothing except possibly "scenery" and "concealed" items are).
  1187. !   Locale(object) runs through the "tail end" of a Look-style room
  1188. !   description for the contents of the object, printing up suitable
  1189. !   descriptions as it goes.
  1190. ! ----------------------------------------------------------------------------
  1191.  
  1192. [ SayWhatsOn descon j f;
  1193.   if (descon==parent(player)) rfalse;
  1194.   objectloop (j in descon)
  1195.       if (j hasnt concealed && j hasnt scenery) f=1;
  1196.   if (f==0) rfalse;
  1197.   L__M(##Look, 4, descon); rtrue;
  1198. ];
  1199.  
  1200. [ NotSupportingThePlayer o i;
  1201.   i=parent(player);
  1202.   while (i~=0 && i~=visibility_ceiling)
  1203.   {   if (i==o) rfalse;
  1204.       i = parent(i);
  1205.       if (i~=0 && i hasnt supporter) rtrue;
  1206.   }
  1207.   rtrue;
  1208. ];
  1209.  
  1210. [ Locale descin text1 text2 o k p j f2 flag;
  1211.  
  1212.   objectloop (o in descin) give o ~workflag;
  1213.  
  1214.   k=0;
  1215.   objectloop (o in descin)
  1216.       if (o hasnt concealed && NotSupportingThePlayer(o))
  1217.       {  #IFNDEF MANUAL_PRONOUNS;
  1218.          PronounNotice(o);
  1219.          #ENDIF;
  1220.          if (o hasnt scenery)
  1221.          {   give o workflag; k++;
  1222.              p=initial; f2=0;
  1223.              if ((o has door || o has container)
  1224.                  && o has open && o provides when_open)
  1225.              {   p = when_open; f2 = 1; jump Prop_Chosen; }
  1226.              if ((o has door || o has container)
  1227.                  && o hasnt open && o provides when_closed)
  1228.              {   p = when_closed; f2 = 1; jump Prop_Chosen; }
  1229.              if (o has switchable
  1230.                  && o has on && o provides when_on)
  1231.              {   p = when_on; f2 = 1; jump Prop_Chosen; }
  1232.              if (o has switchable
  1233.                  && o hasnt on && o provides when_off)
  1234.              {   p = when_off; f2 = 1; }
  1235.  
  1236.              .Prop_Chosen;
  1237.  
  1238.              if (o hasnt moved || o.describe~=NULL || f2==1)
  1239.              {   if (o.describe~=NULL && RunRoutines(o,describe)~=0)
  1240.                  {   flag=1;
  1241.                      give o ~workflag; k--;
  1242.                  }    
  1243.                  else
  1244.                  {   j=o.p;
  1245.                      if (j~=0)
  1246.                      {   new_line;
  1247.                          PrintOrRun(o,p);
  1248.                          flag=1;
  1249.                          give o ~workflag; k--;
  1250.                          if (o has supporter && child(o)~=0) SayWhatsOn(o);
  1251.                      }
  1252.                  }
  1253.              }
  1254.          }
  1255.          else
  1256.              if (o has supporter && child(o)~=0) SayWhatsOn(o);
  1257.       }
  1258.  
  1259.   if (k==0) return 0;
  1260.  
  1261.   if (text1~=0)
  1262.   {   new_line;
  1263.       if (flag==1) text1=text2;
  1264.       print (string) text1, " ";
  1265.       WriteListFrom(child(descin),
  1266.           ENGLISH_BIT + WORKFLAG_BIT + RECURSE_BIT
  1267.           + PARTINV_BIT + TERSE_BIT + CONCEAL_BIT);
  1268.       return k;
  1269.   }
  1270.            
  1271.   if (flag==1) L__M(##Look,5,descin); else L__M(##Look,6,descin);
  1272. ];
  1273.  
  1274. ! ----------------------------------------------------------------------------
  1275. !   Looking.  LookSub(1) is allowed to abbreviate long descriptions, but
  1276. !     LookSub(0) (which is what happens when the Look action is generated)
  1277. !     isn't.  (Except that these are over-ridden by the player-set lookmode.)
  1278. ! ----------------------------------------------------------------------------
  1279.  
  1280. [ LMode1Sub; lookmode=1; print (string) Story; L__M(##LMode1); ];  ! Brief
  1281.  
  1282. [ LMode2Sub; lookmode=2; print (string) Story; L__M(##LMode2); ];  ! Verbose
  1283.  
  1284. [ LMode3Sub; lookmode=3; print (string) Story; L__M(##LMode3); ];  ! Superbrief
  1285.  
  1286. [ NoteArrival descin;
  1287.   descin=location;
  1288.   if (descin~=lastdesc)
  1289.   {   if (descin.initial~=0) PrintOrRun(descin, initial);
  1290.       descin=location;
  1291.       NewRoom();
  1292.       lastdesc=descin;
  1293.   }
  1294. ];
  1295.  
  1296. [ ScoreArrival;
  1297.   if (location hasnt visited)
  1298.   {   give location visited;
  1299.       if (location has scored)
  1300.       {   score = score + ROOM_SCORE;
  1301.           places_score = places_score + ROOM_SCORE;
  1302.       }
  1303.   }
  1304. ];
  1305.  
  1306. [ LookSub allow_abbrev  visibility_levels i j k;
  1307.   if (parent(player)==0) return RunTimeError(10);
  1308.  
  1309.   .MovedByInitial;
  1310.   if (location == thedark) visibility_ceiling = thedark;
  1311.   else
  1312.   {   visibility_levels = 1;
  1313.       visibility_ceiling = parent(player);
  1314.       while ((parent(visibility_ceiling) ~= 0)
  1315.              && (visibility_ceiling hasnt container
  1316.                  || visibility_ceiling has open
  1317.                  || visibility_ceiling has transparent))
  1318.       {   visibility_ceiling = parent(visibility_ceiling);
  1319.           visibility_levels++;
  1320.       }
  1321.       if (visibility_ceiling == location)
  1322.       {   NoteArrival();
  1323.           if (visibility_ceiling ~= location) jump MovedByInitial;
  1324.       }
  1325.   }
  1326.  
  1327.   !   Printing the top line: e.g.
  1328.   !   Octagonal Room (on the table) (as Frodo)
  1329.  
  1330.   new_line;
  1331.   style bold;
  1332.   if (visibility_levels == 0) print (name) thedark;
  1333.   else
  1334.   {   if (visibility_ceiling ~= location) print (The) visibility_ceiling;
  1335.       else print (name) visibility_ceiling;
  1336.   }
  1337.   style roman;
  1338.  
  1339.   for (j=1, i=parent(player):j<visibility_levels:j++, i=parent(i))
  1340.       if (i has supporter) L__M(##Look,1,i);
  1341.                       else L__M(##Look,2,i);
  1342.  
  1343.   if (print_player_flag==1) L__M(##Look,3,player);
  1344.   new_line;
  1345.  
  1346.   !   The room description (if visible)
  1347.  
  1348.   if (lookmode<3 && visibility_ceiling==location)
  1349.   {   if ((allow_abbrev~=1) || (lookmode==2) || (location hasnt visited))
  1350.       {   if (location.describe~=NULL) RunRoutines(location,describe);
  1351.           else
  1352.           {   if (location.description==0) RunTimeError(11,location);
  1353.               else PrintOrRun(location,description);
  1354.           }
  1355.       }
  1356.   }
  1357.  
  1358.   if (visibility_levels == 0) Locale(thedark);
  1359.   else
  1360.   {   for (i=player, j=visibility_levels: j>0: j--, i=parent(i))
  1361.           give i workflag;
  1362.       
  1363.       for (j=visibility_levels: j>0: j--)
  1364.       {   for (i=player, k=0: k<j: k++) i=parent(i);
  1365.           if (i.inside_description~=0)
  1366.           {   new_line; PrintOrRun(i,inside_description); }
  1367.           Locale(i);
  1368.       }
  1369.   }
  1370.  
  1371.   LookRoutine();
  1372.   ScoreArrival();
  1373.  
  1374.   action=##Look;
  1375.   if (AfterRoutines()==1) rtrue;
  1376. ];
  1377.  
  1378. [ ExamineSub i;
  1379.   if (location==thedark) return L__M(##Examine,1);
  1380.   i=noun.description;
  1381.   if (i==0)
  1382.   {   if (noun has container) <<Search noun>>;
  1383.       if (noun has switchable) { L__M(##Examine,3,noun); rfalse; }
  1384.       return L__M(##Examine,2,noun);
  1385.   }
  1386.   PrintOrRun(noun, description);
  1387.   if (noun has switchable) L__M(##Examine,3,noun);
  1388.   if (AfterRoutines()==1) rtrue;
  1389. ];
  1390.  
  1391. [ LookUnderSub;
  1392.   if (location==thedark) return L__M(##LookUnder,1);
  1393.   L__M(##LookUnder,2);
  1394. ];
  1395.  
  1396. [ SearchSub i f;
  1397.   if (location==thedark) return L__M(##Search,1,noun);
  1398.   if (ObjectIsUntouchable(noun)) return;
  1399.   objectloop (i in noun) if (i hasnt concealed && i hasnt scenery) f=1;
  1400.   if (noun has supporter)
  1401.   {   if (f==0) return L__M(##Search,2,noun);
  1402.       return L__M(##Search,3,noun);
  1403.   }
  1404.   if (noun hasnt container) return L__M(##Search,4,noun);
  1405.   if (noun hasnt transparent && noun hasnt open)
  1406.       return L__M(##Search,5,noun);
  1407.   if (AfterRoutines()==1) rtrue;
  1408.  
  1409.   i=children(noun);
  1410.   if (f==0) return L__M(##Search,6,noun);
  1411.   L__M(##Search,7,noun);
  1412. ];
  1413.  
  1414. ! ----------------------------------------------------------------------------
  1415. !   Verbs which change the state of objects without moving them
  1416. ! ----------------------------------------------------------------------------
  1417.  
  1418. [ UnlockSub;
  1419.   if (ObjectIsUntouchable(noun)) return;
  1420.   if (noun hasnt lockable) return L__M(##Unlock,1,noun);
  1421.   if (noun hasnt locked)   return L__M(##Unlock,2,noun);
  1422.   if (noun.with_key~=second) return L__M(##Unlock,3,second);
  1423.   give noun ~locked;
  1424.   if (AfterRoutines()==1) rtrue;
  1425.   if (keep_silent==1) rtrue;
  1426.   L__M(##Unlock,4,noun);
  1427. ];
  1428.  
  1429. [ LockSub;
  1430.   if (ObjectIsUntouchable(noun)) return;
  1431.   if (noun hasnt lockable) return L__M(##Lock,1,noun);
  1432.   if (noun has locked)     return L__M(##Lock,2,noun);
  1433.   if (noun has open)       return L__M(##Lock,3,noun);
  1434.   if (noun.with_key~=second) return L__M(##Lock,4,second);
  1435.   give noun locked;
  1436.   if (AfterRoutines()==1) rtrue;
  1437.   if (keep_silent==1) rtrue;
  1438.   L__M(##Lock,5,noun);
  1439. ];
  1440.  
  1441. [ SwitchonSub;
  1442.   if (ObjectIsUntouchable(noun)) return;
  1443.   if (noun hasnt switchable) return L__M(##SwitchOn,1,noun);
  1444.   if (noun has on) return L__M(##SwitchOn,2,noun);
  1445.   give noun on;
  1446.   if (AfterRoutines()==1) rtrue;
  1447.   if (keep_silent==1) rtrue;
  1448.   L__M(##SwitchOn,3,noun);
  1449. ];
  1450.  
  1451. [ SwitchoffSub;
  1452.   if (ObjectIsUntouchable(noun)) return;
  1453.   if (noun hasnt switchable) return L__M(##SwitchOff,1,noun);
  1454.   if (noun hasnt on) return L__M(##SwitchOff,2,noun);
  1455.   give noun ~on;
  1456.   if (AfterRoutines()==1) rtrue;
  1457.   if (keep_silent==1) rtrue;
  1458.   L__M(##SwitchOff,3,noun);
  1459. ];
  1460.  
  1461. [ OpenSub;
  1462.   if (ObjectIsUntouchable(noun)) return;
  1463.   if (noun hasnt openable) return L__M(##Open,1,noun);
  1464.   if (noun has locked)     return L__M(##Open,2,noun);
  1465.   if (noun has open)       return L__M(##Open,3,noun);
  1466.   give noun open;
  1467.   if (AfterRoutines()==1) rtrue;
  1468.   if (keep_silent==1) rtrue;
  1469.   if (noun has container && noun hasnt transparent && child(noun)~=0
  1470.       && IndirectlyContains(noun,player)==0)
  1471.       return L__M(##Open,4,noun);
  1472.   L__M(##Open,5,noun);
  1473. ];
  1474.  
  1475. [ CloseSub;
  1476.   if (ObjectIsUntouchable(noun)) return;
  1477.   if (noun hasnt openable) return L__M(##Close,1,noun);
  1478.   if (noun hasnt open)     return L__M(##Close,2,noun);
  1479.   give noun ~open;
  1480.   if (AfterRoutines()==1) rtrue;
  1481.   if (keep_silent==1) rtrue;
  1482.   L__M(##Close,3,noun);
  1483. ];
  1484.  
  1485. [ DisrobeSub;
  1486.   if (ObjectIsUntouchable(noun)) return;
  1487.   if (noun hasnt worn) return L__M(##Disrobe,1,noun);
  1488.   give noun ~worn;
  1489.   if (AfterRoutines()==1) rtrue;
  1490.   if (keep_silent==1) rtrue;
  1491.   L__M(##Disrobe,2,noun);
  1492. ];
  1493.  
  1494. [ WearSub;
  1495.   if (ObjectIsUntouchable(noun)) return;
  1496.   if (noun hasnt clothing)  return L__M(##Wear,1,noun);
  1497.   if (parent(noun)~=player) return L__M(##Wear,2,noun);
  1498.   if (noun has worn)        return L__M(##Wear,3,noun);
  1499.   give noun worn;
  1500.   if (AfterRoutines()==1) rtrue;
  1501.   if (keep_silent==1) rtrue;
  1502.   L__M(##Wear,4,noun);
  1503. ];
  1504.  
  1505. [ EatSub;
  1506.   if (ObjectIsUntouchable(noun)) return;
  1507.   if (noun hasnt edible) return L__M(##Eat,1,noun);
  1508.   remove noun;
  1509.   if (AfterRoutines()==1) rtrue;
  1510.   if (keep_silent==1) rtrue;
  1511.   L__M(##Eat,2,noun);
  1512. ];
  1513.  
  1514. ! ----------------------------------------------------------------------------
  1515. !   Verbs which are really just stubs (anything which happens for these
  1516. !   actions must happen in before rules)
  1517. ! ----------------------------------------------------------------------------
  1518.  
  1519. [ YesSub; L__M(##Yes); ];
  1520. [ NoSub; L__M(##No); ];
  1521. [ BurnSub; L__M(##Burn,1,noun); ];
  1522. [ PraySub; L__M(##Pray,1,noun); ];
  1523. [ WakeSub; L__M(##Wake,1,noun); ];
  1524. [ WakeOtherSub;
  1525.   if (ObjectIsUntouchable(noun)) return;
  1526.   if (RunLife(noun,##WakeOther)~=0) rfalse;
  1527.   L__M(##WakeOther,1,noun);
  1528. ];
  1529. [ ThinkSub; L__M(##Think,1,noun); ];
  1530. [ SmellSub; L__M(##Smell,1,noun); ];
  1531. [ ListenSub; L__M(##Listen,1,noun); ];
  1532. [ TasteSub; L__M(##Taste,1,noun); ];
  1533. [ DigSub; L__M(##Dig,1,noun); ];
  1534. [ CutSub; L__M(##Cut,1,noun); ];
  1535. [ JumpSub; L__M(##Jump,1,noun); ];
  1536. [ JumpOverSub; L__M(##JumpOver,1,noun); ];
  1537. [ TieSub; L__M(##Tie,1,noun); ];
  1538. [ DrinkSub; L__M(##Drink,1,noun); ];
  1539. [ FillSub; L__M(##Fill,1,noun); ];
  1540. [ SorrySub; L__M(##Sorry,1,noun); ];
  1541. [ StrongSub; L__M(##Strong,1,noun); ];
  1542. [ MildSub; L__M(##Mild,1,noun); ];
  1543. [ SwimSub; L__M(##Swim,1,noun); ];
  1544. [ SwingSub; L__M(##Swing,1,noun); ];
  1545. [ BlowSub; L__M(##Blow,1,noun); ];
  1546. [ RubSub; L__M(##Rub,1,noun); ];
  1547. [ SetSub; L__M(##Set,1,noun); ];
  1548. [ SetToSub; L__M(##SetTo,1,noun); ];
  1549. [ WaveHandsSub; L__M(##WaveHands,1,noun); ];
  1550. [ BuySub; L__M(##Buy,1,noun); ];
  1551. [ SingSub; L__M(##Sing,1,noun); ];
  1552. [ ClimbSub; L__M(##Climb,1,noun); ];
  1553. [ SleepSub; L__M(##Sleep,1,noun); ];
  1554. [ ConsultSub; L__M(##Consult,1,noun); ];
  1555. [ TouchSub;
  1556.   if (noun==player) return L__M(##Touch,3,noun);
  1557.   if (ObjectIsUntouchable(noun)) return;
  1558.   if (noun has animate) return L__M(##Touch,1,noun);
  1559.   L__M(##Touch,2,noun); ];
  1560. [ WaveSub;
  1561.   if (parent(noun)~=player) return L__M(##Wave,1,noun);
  1562.   L__M(##Wave,2,noun); ];
  1563. [ PullSub;
  1564.   if (ObjectIsUntouchable(noun)) return;
  1565.   if (noun has static)   return L__M(##Pull,1,noun);
  1566.   if (noun has scenery)  return L__M(##Pull,2,noun);
  1567.   if (noun has animate)  return L__M(##Pull,4,noun);
  1568.   L__M(##Pull,3,noun);
  1569. ];
  1570. [ PushSub;
  1571.   if (ObjectIsUntouchable(noun)) return;
  1572.   if (noun has static)   return L__M(##Push,1,noun);
  1573.   if (noun has scenery)  return L__M(##Push,2,noun);
  1574.   if (noun has animate)  return L__M(##Pull,4,noun);
  1575.   L__M(##Push,3,noun);
  1576. ];
  1577. [ TurnSub;
  1578.   if (ObjectIsUntouchable(noun)) return;
  1579.   if (noun has static)   return L__M(##Turn,1,noun);
  1580.   if (noun has scenery)  return L__M(##Turn,2,noun);
  1581.   if (noun has animate)  return L__M(##Pull,4,noun);
  1582.   L__M(##Turn,3,noun);
  1583. ];
  1584.  
  1585. [ WaitSub;
  1586.   if (AfterRoutines()==1) rtrue;
  1587.   L__M(##Wait,1,noun);
  1588. ];
  1589.  
  1590. [ PushDirSub; L__M(##PushDir,1,noun); ];
  1591. [ AllowPushDir i;
  1592.   if (parent(second)~=compass) return L__M(##PushDir,2,noun);
  1593.   if (second==u_obj or d_obj)  return L__M(##PushDir,3,noun);
  1594.   AfterRoutines(); i=noun; move i to player;
  1595.   <Go second>;
  1596.   if (location==thedark) move i to real_location;
  1597.   else move i to location;
  1598. ];
  1599.  
  1600. [ SqueezeSub;
  1601.   if (ObjectIsUntouchable(noun)) return;
  1602.   if (noun has animate) return L__M(##Squeeze,1,noun);
  1603.   L__M(##Squeeze,2,noun);
  1604. ];
  1605.  
  1606. [ ThrowAtSub;
  1607.   if (ObjectIsUntouchable(noun)) return;
  1608.   if (second>1)
  1609.   {   action=##ThrownAt;
  1610.       if (RunRoutines(second,before)~=0) { action=##ThrowAt; rtrue; }
  1611.       action=##ThrowAt;
  1612.   }
  1613.   if (second hasnt animate) return L__M(##ThrowAt,1);
  1614.   if (RunLife(second,##ThrowAt)~=0) rfalse;
  1615.   L__M(##ThrowAt,2,noun);
  1616. ];
  1617.  
  1618. [ AttackSub;
  1619.   if (ObjectIsUntouchable(noun)) return;
  1620.   if (noun has animate && RunLife(noun,##Attack)~=0) rfalse;
  1621.   L__M(##Attack,1,noun); ];
  1622.  
  1623. [ KissSub;
  1624.   if (ObjectIsUntouchable(noun)) return;
  1625.   if (RunLife(noun,##Kiss)~=0) rfalse;
  1626.   if (noun==player) return L__M(##Touch,3,noun);
  1627.   L__M(##Kiss,1,noun);
  1628. ];
  1629.  
  1630. [ AnswerSub;
  1631.   if (RunLife(second,##Answer)~=0) rfalse;
  1632.   L__M(##Answer,1,noun);
  1633. ];  
  1634.  
  1635. [ TellSub;
  1636.   if (noun==player) return L__M(##Tell,1,noun);
  1637.   if (RunLife(noun,##Tell)~=0) rfalse;
  1638.   L__M(##Tell,2,noun);
  1639. ];  
  1640.   
  1641. [ AskSub;
  1642.   if (RunLife(noun,##Ask)~=0) rfalse;
  1643.   L__M(##Ask,1,noun);
  1644. ];  
  1645.  
  1646. [ AskForSub;
  1647.   if (noun==player) <<Inv>>;
  1648.   L__M(##Order,1,noun);
  1649. ];
  1650.  
  1651. ! ----------------------------------------------------------------------------
  1652. !   Debugging verbs
  1653. ! ----------------------------------------------------------------------------
  1654.  
  1655. #IFDEF DEBUG;
  1656. [ TraceOnSub; parser_trace=1; "[Trace on.]"; ];
  1657. [ TraceLevelSub; parser_trace=noun;
  1658.   print "[Parser tracing set to level ", parser_trace, ".]^"; ];
  1659. [ TraceOffSub; parser_trace=0; "Trace off."; ];
  1660. [ RoutinesOnSub;  debug_flag=debug_flag | 1; "[Message listing on.]"; ];
  1661. [ RoutinesOffSub; debug_flag=debug_flag & 6; "[Message listing off.]"; ];
  1662. [ ActionsOnSub;  debug_flag=debug_flag | 2; "[Action listing on.]"; ];
  1663. [ ActionsOffSub; debug_flag=debug_flag & 5; "[Action listing off.]"; ];
  1664. [ TimersOnSub;  debug_flag=debug_flag | 4; "[Timers listing on.]"; ];
  1665. [ TimersOffSub; debug_flag=debug_flag & 3; "[Timers listing off.]"; ];
  1666. [ CommandsOnSub;
  1667.   @output_stream 4; xcommsdir=1; "[Command recording on.]"; ];
  1668. [ CommandsOffSub;
  1669.   if (xcommsdir==1) @output_stream -4;
  1670.   xcommsdir=0;
  1671.   "[Command recording off.]"; ];
  1672. [ CommandsReadSub;
  1673.   @input_stream 1; xcommsdir=2; "[Replaying commands.]"; ];
  1674. [ PredictableSub i; i=random(-100);
  1675.   "[Random number generator now predictable.]"; ];
  1676. [ XTestMove obj dest;
  1677.   if ((obj<=InformLibrary) || (obj == LibraryMessages) || (obj in 1))
  1678.      "[Can't move ", (name) obj, ": it's a system object.]";
  1679.   while (dest ~= 0)
  1680.   {   if (dest == obj)
  1681.           "[Can't move ", (name) obj, ": it would contain itself.]";
  1682.       dest = parent(dest);
  1683.   }
  1684.   rfalse;
  1685. ];
  1686. [ XPurloinSub;
  1687.   if (XTestMove(noun,player)) return;
  1688.   move noun to player; give noun moved ~concealed;
  1689.   "[Purloined.]"; ];
  1690. [ XAbstractSub;
  1691.   if (XTestMove(noun,second)) return;
  1692.   move noun to second; "[Abstracted.]"; ];
  1693. [ XObj obj f;
  1694.   if (parent(obj) == 0) print (name) obj; else print (a) obj;
  1695.   print " (", obj, ") ";
  1696.   if (f==1 && parent(obj) ~= 0)
  1697.       print "(in ", (name) parent(obj), " ", parent(obj), ")";
  1698.   new_line;
  1699.   if (child(obj)==0) rtrue;
  1700.   if (obj == Class)
  1701.       WriteListFrom(child(obj),
  1702.       NOARTICLE_BIT + INDENT_BIT + NEWLINE_BIT + ALWAYS_BIT, 1);
  1703.   else
  1704.       WriteListFrom(child(obj),
  1705.       FULLINV_BIT + INDENT_BIT + NEWLINE_BIT + ALWAYS_BIT, 1);
  1706. ];
  1707. [ XTreeSub i;
  1708.   if (noun==0)
  1709.   {   objectloop(i) if (parent(i)==0) XObj(i);
  1710.   }
  1711.   else XObj(noun,1);
  1712. ];
  1713. [ GotoSub;
  1714.   if (~~(noun ofclass Object) || (parent(noun)~=0)) "[Not a safe place.]";
  1715.   PlayerTo(noun);
  1716. ];
  1717. [ GonearSub x; x=noun; while (parent(x)~=0) x=parent(x); PlayerTo(x); ];
  1718. [ Print_ScL obj; print_ret ++x_scope_count, ": ", (a) obj, " (", obj, ")"; ];
  1719. [ ScopeSub; x_scope_count=0; LoopOverScope(#r$Print_ScL, noun);
  1720.   if (x_scope_count==0) "Nothing is in scope.";
  1721. ];
  1722. #ENDIF;
  1723.  
  1724. ! ----------------------------------------------------------------------------
  1725. !   Finally: the mechanism for library text (the text is in the language defn)
  1726. ! ----------------------------------------------------------------------------
  1727.  
  1728. [ L__M act n x1 s;
  1729.   s=sw__var; sw__var=act; if (n==0) n=1;
  1730.   L___M(n,x1);
  1731.   sw__var=s;
  1732. ];
  1733.  
  1734. [ L___M n x1 s;
  1735.   s=action;
  1736.   lm_n=n; lm_o=x1;
  1737.   action=sw__var;
  1738.   if (RunRoutines(LibraryMessages,before)~=0) { action=s; rfalse; }
  1739.   action=s;
  1740.  
  1741.   LanguageLM(n, x1);
  1742. ];
  1743.  
  1744. ! ----------------------------------------------------------------------------
  1745.